using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.IO;
using System.Security.Principal;
using System.Diagnostics;
using System.Threading;
using System.Collections.Specialized;

namespace CodePlex.Resourceful
{
    public class HttpContextAdapter : IHttpContext
    {

        private readonly HttpContext _context;

        private readonly IHttpRequest _request;
        private readonly IHttpResponse _response;

        private readonly Uri _rootUri;

        public HttpContextAdapter(HttpContext context, Uri rootUri)
        {
            _context = context;
            _request = new InternalRequest(_context, rootUri);
            _response = new InternalResponse(_context);
            _rootUri = rootUri;
        }

        public IHttpRequest Request
        {
            get { return _request; }
        }

        public IHttpResponse Response
        {
            get { return _response; }
        }

        public Uri RootUri
        {
            get { return _rootUri; }
        }




       

        private class InternalResponse : IHttpResponse
        {
            private readonly HttpContext _context;
            private NameValuePairs _headers = new NameValuePairs();
            private bool _isEnded;


            public InternalResponse(HttpContext context)
            {
                _context = context;
            }



            public string ContentType
            {
                get
                {
                    return _context.Response.ContentType;
                }
                set
                {
                    _context.Response.ContentType = value;
                }
            }

            public int StatusCode
            {
                get
                {
                    return _context.Response.StatusCode;
                }
                set
                {
                    _context.Response.StatusCode = value;
                }
            }

            public string StatusDescription
            {
                get
                {
                    return _context.Response.StatusDescription;
                }
                set
                {
                    _context.Response.StatusDescription = value;
                }
            }

            public long ContentLength
            {

                set
                {
                   this.SetHeader(HttpHeader.ContentLength, value.ToString());
                }
            }


            

            public void SetHeader(string name, string value)
            {
                // use a buffer (to avoid duplicates)
                _headers[name] = value;
                
            }

            public Stream GetOutputStream()
            {
                this.SendHeaders();
                return _context.Response.OutputStream;
            }


           

            public void End()
            {
                this.SendHeaders();


                // TODO ??? currently needed for cassini
                Thread.Sleep(10);


                _context.Response.End();
       
                _isEnded = true;
            }

            public bool IsEnded
            {
                get { return _isEnded; }
            }




            private void SendHeaders()
            {
                if (_headers != null)
                {
                    foreach (string header in _headers.Keys)
                    {
                        _context.Response.AddHeader(header, _headers[header]);
                    }
                    _headers = null;
                }

            }




        }


        private class InternalRequest : IHttpRequest
        {


            private readonly HttpContext _context;
            private readonly Uri _rootUri;
            public InternalRequest(HttpContext context, Uri rootUri)
            {
                _context = context;
                _rootUri = rootUri;
            }

           

            public string HttpMethod
            {
                get { return _context.Request.HttpMethod; }
            }

            public ReadOnlyList<string> AcceptTypes
            {
                get { return InternalUtils.GetAcceptTypes(_context.Request.AcceptTypes);  }
            }



           

            public bool IsRelative
            {
                get { return InternalUtils.IsRelative(_rootUri, _context.Request.Url); }
            }

            public string RelativeUri
            {
                get
                {
                    return InternalUtils.RelativeUri(_rootUri, _context.Request.Url);
                }
            }

          
            public string ContentType
            {
                get { return _context.Request.ContentType; }
            }



            public Stream GetRequestStream()
            {
                return _context.Request.InputStream;
            }



            public NameValuePairs Headers
            {
                get { return NameValuePairs.From(_context.Request.Headers); }
            }

           
        }

        public string BasicAuthUsername
        {
            get
            {

                return InternalUtils.GetBasicAuthUsername(this.Request.Headers);
             

            }
        }

        public string BasicAuthPassword
        {
            get
            {
                return InternalUtils.GetBasicAuthPassword(this.Request.Headers);

            }
        }
       
    }

}
